package cn.xzqwjw.taskmanager.domain.vo;

import cn.xzqwjw.taskmanager.common.customEnum.ResponseCodeEnum;
import lombok.Data;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Collection;

/*
 * 1、异常处理规范
 * 不要在业务代码中进行捕获异常
 * 即 dao、service、controller 层的所有异常都全部抛出到上层
 * 这样不会导致业务代码中的一堆 try-catch ，这样会混乱业务代码
 * 2、统一返回结果集
 * 不要使用 Map 来返回结果, Map 不易控制且容易犯错,
 * 应该定义一个 Java 实体类. 来表示统一结果来返回
 * 具体文章参考下面两篇：
 * https://www.jb51.net/article/153973.htm
 * https://www.jb51.net/article/155785.htm
 *
 * 一般只有查询方法需要调用 ResultBean.success(Collection<V> data) 来返回 N 条数据
 * 其他诸如删除, 修改等方法都应该调用 ResultBean.success()
 * 即在业务代码中只处理正确的功能, 不对异常做任何判断
 * 也不需要对 update 或 delete 的更新条数做判断(个人建议, 实际需要根据业务)
 * 只要没有抛出异常, 我们就认为用户操作成功了
 * 且操作成功的提示信息在前端处理, 不要后台返回 “操作成功” 等字段
 * 如果是成功返回，则返回
 * statusCode：20000
 * message: ''
 * data: null 或者是 data
 * 如果发生错误，则返回
 * statusCode: 40400 || ...各种错误代码
 * message: '错误信息'
 * data: null
 */

/**
 * 返回服务器响应的bean类
 *
 * @author rush
 */
@Data
@Component
public class ResponseVo implements Serializable {

  private static final long serialVersionUID = 1L;

  /**
   * 状态码，表示 response 的状态码，为Code枚举值
   */
  private String statusCode;

  /**
   * 返回信息的介绍
   */
  private String message;

  /**
   * 如果返回的信息带数据对象，用这个值传递
   */
  private Object data = null;

  /**
   * 构建函数
   */
  public ResponseVo() {
  }

  public ResponseVo(String statusCode, String message, Object data) {
    this.statusCode = statusCode;
    this.message = message;
    this.data = data;
  }

  // ==================== 成功处理 ====================

  /**
   * 不带参数的success()方法，常用于返回操作成功标识
   */
  public static ResponseVo success() {
    ResponseVo res = new ResponseVo();
    res.setStatusCode("20000");
    res.setMessage("OK");
    res.setData(null);
    return res;
  }

  /**
   * 返回带成功状态码的success()方法，常用于返回添加删除修改等操作成功标识
   */
  public static ResponseVo success(String message) {
    ResponseVo res = new ResponseVo();
    res.setStatusCode("20000");
    res.setMessage(message);
    res.setData(null);
    return res;
  }

  /**
   * 返回带成功状态码和信息的success()方法，常用于返回添加删除修改等操作成功标识
   */
  public static ResponseVo success(String statusCode, String message) {
    ResponseVo res = new ResponseVo();
    res.setStatusCode(statusCode);
    res.setMessage(message);
    res.setData(null);
    return res;
  }

  /**
   * 返回带成功状态码的success()方法，常用于返回添加删除修改等操作成功标识
   */
  public static ResponseVo success(ResponseCodeEnum codeEnum) {
    ResponseVo res = new ResponseVo();
    res.setStatusCode(codeEnum.getStatusCode());
    res.setMessage(codeEnum.getMessage());
    res.setData(null);
    return res;
  }

  /**
   * 返回带成功状态码的success()方法，常用于返回添加删除修改等操作成功标识
   */
  public static ResponseVo success(ResponseCodeEnum codeEnum, Object data) {
    ResponseVo res = new ResponseVo();
    res.setStatusCode(codeEnum.getStatusCode());
    res.setMessage(codeEnum.getMessage());
    res.setData(data);
    return res;
  }

  /**
   * 返回带成功状态码的success()方法，常用于返回添加删除修改等操作成功标识
   */
  public static ResponseVo success(ResponseCodeEnum codeEnum, Collection<?> data) {
    ResponseVo res = new ResponseVo();
    res.setStatusCode(codeEnum.getStatusCode());
    res.setMessage(codeEnum.getMessage());
    res.setData(data);
    return res;
  }

  /**
   * 返回一个对象的success()方法，常用于返回查询某一个结果
   */
  public static ResponseVo success(Object obj) {
    ResponseVo res = new ResponseVo();
    res.setStatusCode("20000");
    res.setMessage("");
    res.setData(obj);
    return res;
  }

  /**
   * 带结果集的success()方法，常用于返回查询某一个结果集
   */
  public static ResponseVo success(Collection<?> data) {
    ResponseVo res = new ResponseVo();
    res.setStatusCode("20000");
    res.setMessage("");
    res.setData(data);
    return res;
  }

  // ==================== 错误处理 ====================

  /**
   * 只返回带错误信息的 error()方法，常用于返回操作失败信息
   */
  public static ResponseVo error(String message) {
    ResponseVo res = new ResponseVo();
    res.setStatusCode("40000");
    res.setMessage(message);
    res.setData(null);
    return res;
  }

  /**
   * 记录error的方法
   */
  public static ResponseVo error(String statusCode, String message) {
    ResponseVo res = new ResponseVo();
    res.setStatusCode(statusCode);
    res.setMessage(message);
    res.setData(null);
    return res;
  }

  /**
   * 返回带错误状态码的 error()方法，常用于返回操作失败信息
   */
  public static ResponseVo error(ResponseCodeEnum codeEnum) {
    return error(codeEnum.getStatusCode(), codeEnum.getMessage());
  }

}
